import 'dart:async';
import 'dart:convert';
import 'dart:html';
import 'dart:typed_data';
import 'generic_file_handle.dart';

class BlobFile extends GenericFileHandle {
  File _file;
  int _length;

  BlobFile(File file) {
    _file = file;
    _length = _file.size;
  }

  @override
  Future<Uint8List> read(int offset, int length, [int position = 0, String encoding]) async {
    var start = position;
    var end = start + length;
    List<int> bytes = await readBlobAsArrayBuffer(_file.slice(start, end)).stream.first;
    return bytes;
  }

  @override
  Future<Uint8List> readFile({String encoding}) async {
    List list = await readBlobAsArrayBuffer(_file).stream.toList();
    List<int> bytes = list[0];
    return bytes;
  }

  @override
  int get size => _length;

  StreamController readBlobAsArrayBuffer(File file) {
    StreamController _streamController = StreamController();
    var fileReader = FileReader();
    fileReader.onLoad.listen((event) {
      _streamController.sink.add(fileReader.result);
    });
    fileReader.onAbort.listen((event) {
      fileReader.abort();
      _streamController.sink.addError(event);
    });
    fileReader.onAbort.listen((event) {
      _streamController.sink.addError(event);
    });
    fileReader.readAsArrayBuffer(file);
    return _streamController;
  }

  StreamController readBlobAsString(File file) {
    StreamController _streamController = StreamController();
    var fileReader = FileReader();
    fileReader.onLoad.listen((event) {
      _streamController.sink.add(fileReader.result);
    });
    fileReader.onAbort.listen((event) {
      fileReader.abort();
      _streamController.sink.addError(event);
    });
    fileReader.onAbort.listen((event) {
      _streamController.sink.addError(event);
    });
    fileReader.readAsText(file);
    return _streamController;
  }

  @override
  Future<String> readAsString({Encoding encoding}) async {
    List list = await readBlobAsArrayBuffer(_file).stream.toList();
    String content = list[0];
    return content;
  }

  @override
  Stream<List<int>> openStream([int start, int end]) {
    // TODO: implement openStream
    throw UnimplementedError();
  }

  @override
  Future<Map> stat() async {
    return {
      'name': _file.name,
      'lastModified': _file.lastModified,
      'lastModifiedDate': _file.lastModifiedDate,
      'size': _file.size,
      'type': _file.type,
    };
  }
}
